#include <fstream>
#include <string>
#include <cstring>
#include <vector>
#include <map>
#include <dirent.h>
#include <iostream>
#include <limits>
#include <algorithm>
#include "Langue.h"

using namespace std;

vector<string> SegmenteSelonSymbole(const string & str, const string & symbole){
	
	string::size_type lastPos = str.find_first_not_of(symbole, 0);
	string::size_type pos = str.find_first_of(symbole, lastPos);
	
	vector<string> str_segmente;
	
 	while (string::npos != pos || string::npos != lastPos){
      str_segmente.push_back(str.substr(lastPos, pos - lastPos));
      lastPos = str.find_first_not_of(symbole, pos);
      pos = str.find_first_of(symbole, lastPos);
    }
  	return str_segmente;
}

void gestion_fichier(map <string, int> mapMot, string nomFichier,string langue){
	string nom = nomFichier + "-"+langue+".txt";
	ofstream fichier(nom.c_str(), ios::out);  
    if(fichier){
		for(map<string, int>::iterator it=mapMot.begin(); it!=mapMot.end(); ++it){
	    	fichier << (it->second) << "\t" << (it->first) << endl;
		}
    	fichier.close();  // on ferme le fichier
    }
    else
    	cerr << "Impossible d'ouvrir le fichier pour la langue " << langue << endl;
}

bool verification_commentaire(string contenu){
	size_t size = contenu.size() + 1;
	char * buffer = new char[size];
	strncpy( buffer, contenu.c_str(), size );

	if(buffer[0] == '<' && buffer[size-2] == '>')
		return false;
	else
		return true;
}

// Ajoute tous les mots de la ligne.
void ajouterMots(Langue& langue, string& ligne) {
	string delim = " .%/,\"<>!?()[]='_:;0123456789";
	
	vector<string> v(SegmenteSelonSymbole(ligne, delim));
	for (unsigned i  = 0; i < v.size(); i++){
 		langue.ajoute_mot(v[i]);
 	}
}

void ajouterTrigrammes(Langue& langue, string ligne) {
	string delim = ".%/,\"<>!?()[]=_:;";
	
	// Suppression de la ponctuation
	int delimLength = delim.length();
	for(int i=0; i<delimLength; i++)
		ligne.erase(std::remove(ligne.begin(), ligne.end(), delim[i]), ligne.end());
	
	// Transformation de la ligne sous forme de char[].
	int length = ligne.length();
	char* buffer = new char[length+1];
	strncpy( buffer, ligne.c_str(), length );
	
	// Récupération des trigrammes.
	char c[4];
	c[3] = '\0';
	if (length >= 2) {
		c[0] = buffer[0];
		c[1] = buffer[1];
	}
	
	for(int i = 2; i < length; i++) {
		c[2] = buffer[i];
		string trig(c);
		langue.ajoute_trigramme(trig);
		c[0] = c[1];
		c[1] = c[2];
	}
	delete buffer;
}

void lire_fichier(Langue& langue, string nomFichier) {
    ifstream fichier(nomFichier.c_str(), ifstream::in);  // on ouvre en lecture
	int nbLignes = 0;
    if(fichier) { // Si l'ouverture du fichier à réussie.
	    string contenu;  // déclaration d'une chaîne qui contiendra la ligne lue
	    
	    while(fichier.ignore(numeric_limits<int>::max(), '\n')){
			// On parcours toutes les lignes en ignorant le caractère de fin de ligne.
			nbLignes++;
			getline(fichier, contenu);
			// Si la ligne n'est pas un commentaire
			// (nous avons choisi de les ignorer).
			if(verification_commentaire(contenu)){
				ajouterMots(langue, contenu);
				ajouterTrigrammes(langue, contenu);
			}
		}
	    fichier.close();
    }
    else
    	cerr << "Impossible d'ouvrir le fichier " << nomFichier << endl;
}

void populationLangue(string& chemin, vector<Langue>& vect) {
	struct dirent* fichier;
	DIR* dirLangue = NULL;
	DIR* dir = opendir(chemin.c_str());
	
	if (dir != NULL) {
		// Parcours du dossier d'entraînement.
		while( (fichier = readdir(dir)) != NULL) {
			if (fichier->d_name[strlen(fichier->d_name)-1] != '.') {
				// Création de la langue en fonction du nom du dossier de langue.
				Langue l(fichier->d_name);
				// Parcours des fichiers d'entraînements pour la langue.
				string nomDossier = chemin + "/" + fichier->d_name;
				dirLangue = opendir(nomDossier.c_str());
				if (dirLangue != NULL) {
					// Population de la langue
					while( (fichier = readdir(dirLangue)) != NULL) {
						if (fichier->d_name[strlen(fichier->d_name)-1] != '.') {
							lire_fichier(l, nomDossier + "/" + fichier->d_name);
						}
					}
					
					// Sauvegarde de la langue
					vect.push_back(l);
					gestion_fichier(l.get_mapMotsOcc(),"occMot", l.get_nomLangue());
					gestion_fichier(l.get_mapTrigrammesOcc(),"occTri", l.get_nomLangue());
				}
			}
		}
	}
}

int main() {
	// Population de la langue
	string chemin = "./donnees-iso-8859-1/entrainement";
	vector<Langue> vect;
	populationLangue(chemin, vect);
	
	/*
	Langue l("fr");
	lire_fichier(l,"ep-99-12-14.txt");
	lire_fichier(l,"ep-99-12-15.txt");
	lire_fichier(l,"ep-99-12-16.txt");
	lire_fichier(l,"ep-99-12-17.txt");
	
	
	// Ecriture des résultats dans un fichier.
	gestion_fichier(l.get_mapMotsOcc(),"occMot", l.get_nomLangue());
	gestion_fichier(l.get_mapTrigrammesOcc(),"occTri", l.get_nomLangue());
	*/
	
	cout << "Fin du programme atteint" << endl;
	return 0;
}


